<!-- 
ListSetup.vue
这是一个使用 <script setup> 语法创建的列表组件
<script setup> 的特点：
- 更简洁的语法
- 更好的运行时性能
- 更好的 IDE 类型推导支持
- 无需手动返回要暴露给模板的内容
- 推荐用于 Vue 3 项目
-->
<template>
  <div class="list-setup">
    <!-- 列表头部 -->
    <div class="list-setup__header">
      <h3 class="list-setup__title">{{ title }}</h3>
      <div class="list-setup__actions">
        <!-- 搜索框 -->
        <input
          v-model="searchText"
          type="text"
          class="list-setup__search"
          placeholder="搜索..."
          @input="handleSearch"
        />
        <!-- 排序选择 -->
        <select v-model="sortOrder" class="list-setup__sort" @change="handleSort">
          <option value="asc">升序</option>
          <option value="desc">降序</option>
        </select>
      </div>
    </div>

    <!-- 列表内容 -->
    <div class="list-setup__content">
      <!-- 加载状态 -->
      <div v-if="loading" class="list-setup__loading">加载中...</div>

      <!-- 空状态 -->
      <div v-else-if="filteredItems.length === 0" class="list-setup__empty">
        <slot name="empty"> 暂无数据 </slot>
      </div>

      <!-- 列表项 -->
      <TransitionGroup v-else name="list" tag="ul" class="list-setup__items">
        <li
          v-for="item in filteredItems"
          :key="item.id"
          class="list-setup__item"
          :class="{ 'list-setup__item--active': selectedId === item.id }"
          @click="handleItemClick(item)"
        >
          <!-- 自定义列表项内容 -->
          <slot name="item" :item="item" :is-selected="selectedId === item.id">
            {{ item.name }}
          </slot>
        </li>
      </TransitionGroup>
    </div>

    <!-- 列表底部 -->
    <div class="list-setup__footer">
      <slot name="footer"> 共 {{ filteredItems.length }} 项 </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, watch, onMounted } from 'vue'

  // 定义类型
  interface ListItem {
    id: number | string
    name: string
    [key: string]: any
  }

  // 定义 Props
  interface Props {
    title?: string
    items: ListItem[]
    loading?: boolean
  }

  // 定义 Emits
  interface Emits {
    (e: 'select', item: ListItem): void
    (e: 'search', text: string): void
    (e: 'sort', order: 'asc' | 'desc'): void
  }

  // 声明 props 和 emits
  const props = withDefaults(defineProps<Props>(), {
    title: '列表',
    loading: false,
  })

  const emit = defineEmits<Emits>()

  // 响应式状态
  const searchText = ref('')
  const sortOrder = ref<'asc' | 'desc'>('asc')
  const selectedId = ref<number | string | null>(null)

  // 计算属性：过滤和排序后的列表
  const filteredItems = computed(() => {
    let result = [...props.items]

    // 搜索过滤
    if (searchText.value) {
      result = result.filter((item) =>
        item.name.toLowerCase().includes(searchText.value.toLowerCase()),
      )
    }

    // 排序
    result.sort((a, b) => {
      const comparison = a.name.localeCompare(b.name)
      return sortOrder.value === 'asc' ? comparison : -comparison
    })

    return result
  })

  // 方法
  const handleSearch = () => {
    emit('search', searchText.value)
  }

  const handleSort = () => {
    emit('sort', sortOrder.value)
  }

  const handleItemClick = (item: ListItem) => {
    selectedId.value = item.id
    emit('select', item)
  }

  // 侦听器：监听 props.items 的变化
  watch(
    () => props.items,
    () => {
      // 当列表数据变化时，重置搜索和选中状态
      searchText.value = ''
      selectedId.value = null
    },
  )

  // 生命周期钩子
  onMounted(() => {
    console.log('ListSetup 组件已挂载')
  })

  // 暴露给父组件的方法（可选）
  defineExpose({
    // 清除选择
    clearSelection: () => {
      selectedId.value = null
    },
    // 重置搜索
    resetSearch: () => {
      searchText.value = ''
    },
  })
</script>

<style scoped>
  .list-setup {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 16px;
    background: white;
  }

  .list-setup__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
  }

  .list-setup__title {
    margin: 0;
    font-size: 18px;
    color: #333;
  }

  .list-setup__actions {
    display: flex;
    gap: 8px;
  }

  .list-setup__search,
  .list-setup__sort {
    padding: 6px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
  }

  .list-setup__search:focus,
  .list-setup__sort:focus {
    outline: none;
    border-color: #2196f3;
  }

  .list-setup__content {
    min-height: 200px;
  }

  .list-setup__loading,
  .list-setup__empty {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 200px;
    color: #666;
  }

  .list-setup__items {
    color: #ff8800;
    list-style: none;
    padding: 0;
    margin: 0;
  }

  .list-setup__item {
    padding: 12px;
    margin: 4px 0;
    border: 1px solid #eee;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s ease;
  }

  .list-setup__item:hover {
    background: #f5f5f5;
  }

  .list-setup__item--active {
    background: #e3f2fd;
    border-color: #2196f3;
  }

  .list-setup__footer {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #eee;
    color: #666;
    font-size: 14px;
    text-align: right;
  }

  /* 列表项动画 */
  .list-enter-active,
  .list-leave-active {
    transition: all 0.3s ease;
  }

  .list-enter-from,
  .list-leave-to {
    opacity: 0;
    transform: translateX(30px);
  }

  .list-move {
    transition: transform 0.3s ease;
  }
</style>
